package v1

import (
	"fmt"
	. "gintify/core"
	"gintify/model"
	"gintify/response"
	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
	"strconv"
)

type IUserController interface {
	IRestController
	IAuthController
}

type UserController struct {
	// 空结构体
}

func NewUserController() *UserController {
	DB.AutoMigrate(&model.SysUser{})
	//log.Printf("迁移了一次数据库sys_user") 每次启动只执行一次，所以放在这里迁移没有影响
	return &UserController{}
}

// @Summary 新增用户
// @Description 往数据库中新增用户
// @Tags 用户
// @Accept  json
// @Produce  json
// @Security ApiKeyAuth
// @Success 200 {object} model.SysUser "{"code":0,"message":"OK","data": {}}"
// @Router /api/v1/users [post]
func (u UserController) Post(c *gin.Context) {
	var user = model.SysUser{}
	if err := c.ShouldBindJSON(&user); err != nil {
		response.Error(c, "绑定错误", err)
		return
	}
	hashPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
	if err != nil {
		//response.Response(c, http.StatusInternalServerError, 500, "加密错误", nil)
		response.Error(c, "生成Hash密码出错", err)
		return
	}
	//newUser := model.SysUser{
	//	//BaseModel: model.BaseModel{},
	//	Name:     requestUser.Name,
	//	Password: string(hashPassword),
	//}
	user.Password = string(hashPassword)
	if isUserExist(user.Name) {
		response.Fail(c, "用户名已被占用", nil)
		return
	}
	if err := DB.Create(&user).Error; err != nil {
		response.Error(c, "创建失败", err)
		return
	}
	// 颁发token 不是注册，不需要颁发token，该方法仅用于后台新建用户
	//token, err := ReleaseToken(user)
	//if err != nil {
	//	//response.Response(c, http.StatusInternalServerError, 500, "系统异常", nil)
	//	response.Error(c, "系统异常", err)
	//	return
	//}
	response.Success(c, "创建用户成功", user)
}

// @Summary 获取用户列表
// @Description 从数据库中获取用户列表
// @Tags 用户
// @Accept  json
// @Produce  json
// @Security ApiKeyAuth
// @Success 200 {object} []model.SysUser "{"code":0,"message":"OK","data": {}}"
// @Router /api/v1/users [get]
func (u UserController) GetList(c *gin.Context) {
	var users []model.SysUser
	if err := DB.Debug().Preload("Role").Find(&users).Error; err != nil {
		response.Error(c, "查询失败", err)
		return
	}
	if len(users) == 0 {
		response.Success(c, "用户列表为空", nil)
		return
	}
	response.Success(c, "获取用户列表成功", users)
}

// @Summary 获取用户
// @Description 从数据库中获取用户信息
// @Tags 用户
// @Accept  json
// @Produce  json
// @Security ApiKeyAuth
// @Param id path uint64 true "user id in database"
// @Success 200 {object} model.SysUser "{"code":0,"message":"OK","data": {}}"
// @Router /api/v1/users/{id} [get]
func (u UserController) Get(c *gin.Context) {
	var user model.SysUser
	ids := c.Param("id")
	idx, err := strconv.Atoi(ids)
	if err != nil || idx < 1 {
		response.Fail(c, "URL路径有错误", err)
		return
	}

	if err := DB.First(&user, idx).Error; err != nil {
		response.Error(c, "查询失败", err)
		return
	}
	if user.ID == 0 {
		response.Fail(c, "用户不存在", nil)
		return
	}
	response.Success(c, "获取用户信息成功", user)
}

// @Summary 更新用户
// @Description 在数据库中更新用户信息
// @Tags 用户
// @Accept  json
// @Produce  json
// @Security ApiKeyAuth
// @Param id path uint64 true "user id in database"
// @Success 200 {object} model.SysUser "{"code":0,"message":"OK","data": {}}"
// @Router /api/v1/users/{id} [put]
func (u UserController) Put(c *gin.Context) {
	ids := c.Param("id")
	idx, err := strconv.Atoi(ids)
	if err != nil || idx < 1 {
		response.Fail(c, "URL路径有错误", err)
		return
	}
	var user = model.SysUser{}
	if err := c.ShouldBindJSON(&user); err != nil {
		response.Error(c, "绑定错误", nil)
		LG.Errorf("绑定出错%v\n", err)
		return
	}
	var old = model.SysUser{}
	if err := DB.Model(&model.SysUser{}).Debug().First(&old, user.ID).Error; err != nil {
		response.Error(c, "查询失败", err)
		return
	}
	user.Password = ""
	if err := DB.Model(&old).Where("id = ?", idx).Updates(&user).Error; err != nil {
		response.Error(c, "更新失败", err)
		return
	}
	response.Updated(c, "更新用户信息成功", nil)
}

// @Summary 更新用户
// @Description 在数据库中更新用户信息
// @Tags 用户
// @Accept  json
// @Produce  json
// @Security ApiKeyAuth
// @Param id path uint64 true "user id in database"
// @Success 200 {object} model.SysUser "{"code":0,"message":"OK","data": {}}"
// @Router /api/v1/users/{id} [patch]
func (u UserController) Patch(c *gin.Context) {
	id := c.Param("id")
	var user=model.SysUser{}
	if err := c.ShouldBindJSON(&user); err != nil {
		response.Error(c, "绑定错误", err)
		return
	}
	var old = model.SysUser{}
	if err:=DB.Model(&model.SysUser{}).Where("id = ?", id).Preload("Role").First(&old).Error;err!=nil{
		response.Error(c, "查询User失败", err)
		return
	}
	user.Name = ""
	if err := DB.Model(&old).Updates(user).Error;err!=nil{
		response.Error(c, "更新User失败", err)
		return
	}
	response.Updated(c, "更新成功", old)
}

// @Summary 删除用户
// @Description 在数据库中软删除用户
// @Tags 用户
// @Accept  json
// @Produce  json
// @Security ApiKeyAuth
// @Param id path uint64 true "user id in database"
// @Success 200 {object} model.SysUser "{"code":0,"message":"OK","data": {}}"
// @Router /api/v1/users/{id} [delete]
func (u UserController) Delete(c *gin.Context) {
	ids := c.Param("id")
	idx, err := strconv.Atoi(ids)
	if err != nil || idx < 1 {
		response.Fail(c, "URL路径有错误", err)
		return
	}
	if err := DB.Debug().Delete(&model.SysUser{}, idx).Error; err != nil {
		response.Error(c, "删除失败", err)
		return
	}
	response.Deleted(c, "删除成功", nil)
}

// @Summary 注册
// @Description 注册账户, 获取 token
// @Tags Auth
// @Accept  json
// @Produce  json
// @Param body body model.SysUser true "用户注册接口"
// @Success 200 {string} string "{"success":true,"data":{"token":"name"},"msg":"注册成功"}"
// @Router /register [post]
func (u UserController) Register(c *gin.Context) {
	var user = model.SysUser{}
	if err := c.ShouldBindJSON(&user); err != nil {
		response.Error(c, "绑定错误", err)
		return
	}
	fmt.Printf("%v\n", user)
	if isUserExist(user.Name) {
		response.Fail(c, "用户名已被占用", nil)
		return
	}
	// 添加记录
	if err := DB.Create(&user).Error; err != nil {
		response.Error(c, "创建失败", err)
		return
	}
	// 颁发token
	token, err := ReleaseToken(user)
	if err != nil {
		//response.Response(c, http.StatusInternalServerError, 500, "系统异常", nil)
		response.Error(c, "生成Token出错", err)
		return
	}
	response.Success(c, "注册成功", gin.H{"token": token})
}

// @Summary 登录
// @Description 登录账户, 获取 token
// @Tags Auth
// @Accept  json
// @Produce  json
// @Param body body model.SysUser true "用户登录接口"
// @Success 200 {string} string "{"success":true,"data":{"token":"name"},"msg":"登录成功"}"
// @Router /login [post]
func (u UserController) Login(c *gin.Context) {
	var requestUser = model.SysUserLogin{}
	if err := c.ShouldBindJSON(&requestUser); err != nil {
		response.Error(c, "绑定错误", err)
		return
	}
	//fmt.Printf("%v\n", requestUser)
	var user model.SysUser
	if err := DB.Where("name = ?", requestUser.Name).First(&user).Error; err != nil {
		response.Error(c, "查询失败", err)
		return
	}
	if user.ID == 0 {
		response.Fail(c, "用户名不存在", nil)
		return
	}
	// 比对密码
	//log.Printf("pssword %v\npassword %v\n", requestUser.Password, user.Password)
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(requestUser.Password));
		err != nil {
		response.Fail(c, "密码不正确", err)
		return
	}
	// 颁发token
	token, err := ReleaseToken(user)
	if err != nil {
		response.Error(c, "生成token出错", err)
		return
	}
	// 返回token
	response.Success(c, "登录成功", gin.H{"token": token, "user": user})
}

// @Summary 注销
// @Description 注销登录
// @Tags Auth
// @Accept  json
// @Produce  json
// @Security ApiKeyAuth
// @Success 200 {string} string "{"success":true,"data":{"token":"name"},"msg":"注销成功"}"
// @Router /logout [post]
func (u UserController) Logout(c *gin.Context) {
	panic("implement me")
}

func isUserExist(name string) bool {
	return DB.Where("name = ?", name).First(&model.SysUser{}).RowsAffected > 0
}
